/*
 * 
 * Mysql-backed implementation of the photo interface.
 * Needs the following table:
 * 
 * CREATE TABLE  `webdb`.`foto` (
 * `ID` int(10) unsigned NOT NULL auto_increment,
 * `titolo` varchar(200) NOT NULL,
 * `image_uri` varchar(255) NOT NULL,
 * `thumbnail_uri` varchar(255) default NULL,
 * `IDalbum` int(10) unsigned NOT NULL,
 * `tipo` varchar(50) NOT NULL,
 * PRIMARY KEY  (`ID`)
 * );
 * 
 */
package it.univaq.f4i.iw.ex.album.model.impl;

import it.univaq.f4i.iw.ex.album.model.Album;
import it.univaq.f4i.iw.ex.album.model.Comment;
import it.univaq.f4i.iw.ex.album.model.Photo;
import java.io.File;
import java.io.InputStream;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
 *
 * @author Giuseppe Della Penna
 */
public class PhotoMysqlImpl implements Photo {

    private String titolo;
    private int key;
    private String type;
    private Album album;
    private String imageURI;
    private String thumbnailUri;
    private List<Comment> coments;
    //proprietà non esposte dall'interfaccia, usate solo per questa implementazione
    //these properties are not available to the user, but only to the implementation
    //chiave esterna verso il record dell'album 
    //foreign key to the album record
    private int album_key;
    private InputStream image_stream;
    private PhotoAlbumDataLayerMysqlImpl datalayer;

    //notare che i costruttori che seguono sono entrambi
    //package-private, cioè possono essere richiamati
    //solo da classi all'interno dello stesso package
    //(tra cui le API del modello dati), ma risultano
    //invisibili all'utente (che non può usare quindi la
    //new per creare istanze di questa classe)
    //costrutture "vuoto" usato per inizializzare gli oggetti
    //notare che queste classi hanno bisogno di un riferimento
    //alle API del modello dati per eseguire alcune operazioni
    // note that following constructors are
    // package-private, i.e., they can be called
    // only by classes in the same package
    // (including the data layer class), but are
    // invisible to the user (the operator new cannot be
    // used to create instances of this class)
    //  this is an "empty" constructor 
    // note that these classes need a reference
    // to the data layer API to perform some operations
    PhotoMysqlImpl(PhotoAlbumDataLayerMysqlImpl datalayer) {
        titolo = "";
        type = "";
        album = null;
        coments = null;
        image_stream = null;
        thumbnailUri = "";
        imageURI = "";
        key = 0;
        album_key = 0;
        this.datalayer = datalayer;
    }

    //costrutture "helper" che crea un oggetto e lo imposta
    //in base ai valori dei campi nel record corrente di
    //un ResultSet - utile per creare oggetti a partire
    //dai risultati di una query
    //helper constructor which creates an object
    //and sets its contents according to the fields
    //of the current record in the given ResultSet - 
    //useful to create objects from query results
    PhotoMysqlImpl(PhotoAlbumDataLayerMysqlImpl datalayer, ResultSet data) throws SQLException {
        this.datalayer = datalayer;
        key = data.getInt("ID");
        titolo = data.getString("titolo");
        album_key = data.getInt("IDalbum");
        imageURI = data.getString("image_uri");
        thumbnailUri = data.getString("thumbnail_uri");
        type = data.getString("tipo");
        album = null;
        coments = null;
        image_stream = null;
    }

    /**
     * @return the title
     */
    public String getTitle() {
        return titolo;
    }

    /**
     * @param title the title to set
     */
    public void setTitle(String title) {
        this.titolo = title;
    }

    /**
     * @return the image type
     */
    public String getImageType() {
        return type;
    }

    /**
     * @param type the image type to set
     */
    public void setImageType(String type) {
        this.type = type;
    }

    /**
     * @return the image size
     */
    public long getImageSize() {
        return new File(imageURI).length();
    }

    /**
     * @return the comments
     */
    //questo getter implementa una politica di
    //caricamento "lazy" dei commenti aggregati
    //(il caricamento avviene alla prima chiamata
    //al metodo)
    //this getter implements a "lazy loading" policy
    //for the linked comments: they are loaded 
    //only when this method is first called
    public List<Comment> getComments() {
        if (coments == null) {
            coments = datalayer.getCommentsByPhoto(this);
        }
        return coments;
    }

    /**
     * @param comments the comments to set
     */
    public void setComments(List<Comment> comments) {
        this.coments = comments;
    }

    /**
     * @return the key
     */
    public int getKey() {
        return key;
    }

    /**
     * @param key the key to set
     */
    public void setKey(int key) {
        this.key = key;
    }

    /**
     * @return the album
     */
    //questo getter implementa una politica di
    //caricamento "lazy" dell'album aggregato
    //(il caricamento avviene alla prima chiamata
    //al metodo)
    //this getter implements a "lazy loading" policy
    //for the linked album: it is loaded 
    //only when this method is first called
    public Album getAlbum() {
        if (album == null) {
            album = datalayer.getAlbum(album_key);
        }
        return album;
    }

    /**
     * @param album the album to set
     */
    public void setAlbum(Album album) {
        this.album = album;
    }

    /**
     * @return the image uri
     */
    public String getImageUri() {
        return imageURI;
    }

    /**
     * @param imageURI the image uri to set
     */
    void setImageUri(String imageURI) {
        this.imageURI = imageURI;
    }

    /**
     * @return the thumbnail uri
     */
    public String getThumbnailUri() {
        return thumbnailUri;
    }

    /**
     * @param thumbnailUri the thumbnail uri to set
     */
    void setThumbnail_uri(String thumbnailUri) {
        this.thumbnailUri = thumbnailUri;
    }

    //questi due metodi sono utilizzati per manipolare
    //lo stream contenente l'imagine ed associarlo
    //all'oggetto Photo. Questo stream non è visibile
    //all'utente (non è esposto dall'interfaccia),
    //ma è usato dalle API del modello per gestire
    //l'upload delle immagini.
    //these methods are used to manipulate the stream
    //connected to the image and associate it to the 
    //photo object. This stream is not visible to the
    //user, but is used by the data model to handle the image upload.
    public void setImage(InputStream is) {
        image_stream = is;
    }

    InputStream getImage() {
        return image_stream;
    }
}
